home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Texteditors / Origami / Sources / src / keybind / parseasm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-27  |  8.2 KB  |  347 lines

  1. /*{{{}}}*/
  2. /*{{{  #includes*/
  3. #include <ctype.h>
  4. #include <string.h>
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7.  
  8. #define PARSEASM_C
  9. #define CODE_LG_ARRAY
  10.  
  11. #include "keybind.h"
  12. #include <h/codelg.h>
  13. #include <lib/ori_add_lib.h>
  14. /*}}}  */
  15.  
  16. /*{{{  typedef ocl_label*/
  17. typedef struct ocl_label
  18.  { char *name;
  19.    TOKEN *val;
  20.    struct ocl_label *next;
  21.  } ocl_label;
  22. /*}}}  */
  23. /*{{{  variables*/
  24. ocl_label *used_labels;
  25. ocl_label *def_labels;
  26. TOKEN *start_buff;
  27. /*}}}  */
  28.  
  29. /*{{{  create_label*/
  30. private void create_label(ocl_label **labels,TOKEN *buff,unsigned char *str)
  31. { ocl_label *x;
  32.  
  33.   x=kbd_malloc(sizeof(ocl_label)+ustrlen(str)+1);
  34.   x->next= *labels;
  35.   *labels=x;
  36.   x->val=buff;
  37.   strcpy(x->name=(char*)(x+1),(char*)str);
  38. }
  39. /*}}}  */
  40. /*{{{  get_ind_arg*/
  41. private boolean get_ind_arg(TOKEN **buff_p)
  42. { tokens token;
  43.   int fak;
  44.   int add=0;
  45.  
  46.   /*{{{  maybe get offset*/
  47.   while ((token=get_full_token())==ADD)
  48.    { int add_fak=1;
  49.  
  50.      switch (get_full_token())
  51.       { case MINUS:
  52.            if (get_full_token()!=NUMBER)
  53.         default:
  54.               goto error_int_arg;
  55.            add_fak= -1;
  56.         case NUMBER:
  57.            add+=add_fak*tk_val;
  58.            break;
  59.  
  60.       }
  61.    }
  62.   /*}}}  */
  63.   fak=1;
  64.   switch (token)
  65.    { case MINUS:
  66.         if (get_full_token()!=NUMBER)
  67.            goto error_int_arg;
  68.         fak= -1;
  69.      case NUMBER:
  70.         *(*buff_p)++=tk_val*fak+add;
  71.         return(False);
  72.      case NAME:
  73.       { int x;
  74.  
  75.         if ((x=name2msg(tk_string))>=0)
  76.          { *(*buff_p)++=x*fak+add;
  77.            return(False);
  78.          }
  79.         goto error_int_arg;
  80.       }
  81.      case BEGIN:
  82.       { unsigned char hide_var[NAME_LG];
  83.  
  84.         /*{{{  get name for hidden variable*/
  85.         if (get_full_token()!=NAME) goto error_int_arg;
  86.         hide_var[0]='(';
  87.         ustrcpy(hide_var+1,tk_string);
  88.         if (get_full_token()!=END) goto error_int_arg;
  89.         strcat((char*)hide_var,")");
  90.         ustrcpy(tk_string,hide_var);
  91.         /*}}}  */
  92.         /*{{{  look for this hidden variable*/
  93.         { VARS_LIST const *x;
  94.  
  95.           for (x=var_list;;)
  96.              if (!x)
  97.                 goto error_int_arg;
  98.              else if (x->var_name && !ustrcmp(x->var_name,hide_var))
  99.                 break;
  100.              else
  101.                 x=x->next;
  102.           tk_var=x;
  103.         }
  104.         /*}}}  */
  105.       }
  106.      case VARIABLE:
  107.         *(*buff_p)++=tk_var->no+add;
  108.         return(False);
  109.      default:
  110.      error_int_arg:
  111.         m_exit(M_NOVAR);
  112.    }
  113. }
  114. /*}}}  */
  115. /*{{{  get_char_arg*/
  116. private TOKEN *get_char_arg(TOKEN *buff)
  117. {
  118.   switch (get_full_token())
  119.    { case NUMBER:
  120.         *buff++=tk_val;
  121.         return(buff);
  122.      case MACRO:
  123.         if (ustrlen(tk_string)!=1)
  124.            goto char_arg_error;
  125.         *buff++=tk_string[0];
  126.         return(buff);
  127.      default:
  128.      char_arg_error:
  129.         m_exit(M_NOADDCOUNTER);
  130.    }
  131. }
  132. /*}}}  */
  133. /*{{{  get_add_arg*/
  134. private TOKEN *get_add_arg(TOKEN *buff)
  135. { tokens token;
  136.   int add=0;
  137.  
  138.   /*{{{  maybe get offset*/
  139.   while ((token=get_full_token())==ADD)
  140.    { int fak=1;
  141.  
  142.      switch (get_full_token())
  143.       { case MINUS:
  144.            if (get_full_token()!=NUMBER)
  145.         default:
  146.               goto ad_arg_error;
  147.            fak= -1;
  148.         case NUMBER:
  149.            add+=fak*tk_val;
  150.            break;
  151.  
  152.       }
  153.  
  154.    }
  155.   /*}}}  */
  156.   switch (token)
  157.    {
  158.      /*{{{  NUMBER use offset directly*/
  159.      case NUMBER:
  160.         *buff++=tk_val;
  161.         return(buff);
  162.      /*}}}  */
  163.      /*{{{  NAME   use label, maybe mark for backpatching*/
  164.      case NAME:
  165.       { ocl_label *x;
  166.  
  167.         for (x=def_labels;x && strcmp(x->name,(char*)tk_string);x=x->next);
  168.         if (x)
  169.          { *buff=x->val-buff-1+add;
  170.          }
  171.         else
  172.          { create_label(&used_labels,buff,tk_string);
  173.            *buff=start_buff-buff+1+add;
  174.          }
  175.         return(buff+1);
  176.       }
  177.      /*}}}  */
  178.      default:
  179.      ad_arg_error:
  180.         m_exit(M_NOADDCOUNTER);
  181.    }
  182. }
  183. /*}}}  */
  184. /*{{{  parse_asm*/
  185. public TOKEN *parse_asm(TOKEN *buff,unsigned char *name)
  186. { tokens token;
  187.  
  188.   used_labels=0;
  189.   def_labels=0;
  190.   start_buff=buff;
  191.   if (verbose_level>0) fprintf(stderr,M_ASM_1,name);
  192.   begin_parse();
  193.   do
  194.    /*{{{  handle a statement*/
  195.    { check_length(buff);
  196.      token=get_full_token();
  197.      switch (token)
  198.       {
  199.         /*{{{  insert opcode*/
  200.         case OPCODE:
  201.            *buff++=tk_key->num;
  202.            continue;
  203.         /*}}}  */
  204.         /*{{{  single TOKEN macro*/
  205.         case OPERATION:
  206.            if (tk_operation->length!=1) goto asm_error;
  207.            *buff++ = *(tk_operation->ops);
  208.            continue;
  209.         /*}}}  */
  210.         /*{{{  eval, call parse_macro as subroutine call*/
  211.         case EVAL:
  212.          { TOKEN *call;
  213.            TOKEN *jmp;
  214.            boolean foo;
  215.  
  216.            buff=generate_jmp(M_CALL,call=buff,buff);
  217.            buff=generate_jmp(M_JMP,jmp=buff,buff);
  218.            generate_jmp(M_CALL,call,buff);
  219.            if (!(buff=opt_parse_macro(call=buff,0,&foo,False,!demand,True))) return(0);
  220.            *buff++=M_END_MACRO;
  221.            generate_jmp(M_JMP,jmp,buff);
  222.            break;
  223.         }
  224.         /*}}}  */
  225.         /*{{{  number*/
  226.         case NUMBER:
  227.            *buff++=tk_val;
  228.            break;
  229.         /*}}}  */
  230.         /*{{{  string*/
  231.         case MACRO:
  232.          { TOKEN *x;
  233.  
  234.            for (x=tk_macro;*x;*buff++ = *x++);
  235.            break;
  236.          }
  237.         /*}}}  */
  238.         /*{{{  NAME -> ocl-asm-statement or label*/
  239.         case NAME:
  240.          { KEYNAME const *a;
  241.  
  242.            if ((a=name2asm(tk_string)))
  243.             /*{{{  asm-command*/
  244.             { *buff++=a->num;
  245.               switch (cmd_type[a->num-O_NOP])
  246.                { case COM_II:
  247.                     if (get_ind_arg(&buff)) return(0);
  248.                  case COM_I:
  249.                     if (get_ind_arg(&buff)) return(0);
  250.                  case COM:
  251.                     break;
  252.                  case COM_C:
  253.                     if (!(buff=get_char_arg(buff))) return(0);
  254.                     break;
  255.                  case COM_A:
  256.                     if (!(buff=get_add_arg(buff))) return(0);
  257.                     break;
  258.                  case COM_IIP:
  259.                     if (get_ind_arg(&buff)) return(0);
  260.                  case COM_IP:
  261.                     if (get_ind_arg(&buff)) return(0);
  262.                  case COM_P:
  263.                     if (!(buff=get_message(buff))) return(0);
  264.                     break;
  265.                }
  266.               continue;
  267.             }
  268.             /*}}}  */
  269.            else if (tk_string[0]=='.')
  270.             /*{{{  label*/
  271.             { ocl_label *x,*y;
  272.  
  273.               /*{{{  already defined?*/
  274.               for
  275.                ( x=def_labels;
  276.                  x && strcmp(x->name,(char*)tk_string+1);
  277.                  x=x->next
  278.                );
  279.               if (x)
  280.                  if (x->val!=buff)
  281.                   /*{{{  error, duplicate definition*/
  282.                     m_exit(M_DUPDEF);
  283.                   /*}}}  */
  284.                  else
  285.                   /*{{{  same adress used, so ok*/
  286.                     break;
  287.                   /*}}}  */
  288.               /*}}}  */
  289.               /*{{{  backpatch*/
  290.               for (y=0,x=used_labels;x;)
  291.                  if (strcmp(x->name,(char*)tk_string+1))
  292.                   { y=x;
  293.                     x=x->next;
  294.                   }
  295.                  else
  296.                   { *(x->val)+=buff-start_buff-2;
  297.                     if (y)
  298.                      { y->next=x->next;
  299.                        kbd_free(x);
  300.                        x=y->next;
  301.                      }
  302.                     else
  303.                      { used_labels=x->next;
  304.                        kbd_free(x);
  305.                        x=used_labels;
  306.                      }
  307.                   }
  308.               /*}}}  */
  309.               /*{{{  define new*/
  310.               create_label(&def_labels,buff,tk_string+1);
  311.               /*}}}  */
  312.               break;
  313.             }
  314.             /*}}}  */
  315.            else
  316.               goto asm_error;
  317.          }
  318.         /*}}}  */
  319.         /*{{{  ) -> ready*/
  320.         case END:
  321.            break;
  322.         /*}}}  */
  323.         /*{{{  default: error*/
  324.         default:
  325.         asm_error:
  326.            m_exit(M_NOMSTRING);
  327.         /*}}}  */
  328.       }
  329.    }
  330.    /*}}}  */
  331.   while (token!=END);
  332.   if (used_labels)
  333.    { error_po();
  334.      fprintf(stderr,F_ASM_LM,used_labels->name);
  335.      return(0);
  336.    }
  337.   while (def_labels)
  338.    { ocl_label *x;
  339.  
  340.      x=def_labels;
  341.      def_labels=x->next;
  342.      kbd_free(x);
  343.    }
  344.   return(buff);
  345. }
  346. /*}}}  */
  347.